﻿using System.Data.Common;
using System.Windows.Forms;
using Tetris.Game.Common.TetrisCenter.TetrisBase;
using Tetris.Game.ControlsBase;

namespace Tetris.Game.Common.TetrisCenter
{
    public unsafe static class TetrisGameEx
    {
        public static Point GetRotatePoint(this RotationAngle angle, int x, int y, int centerX, int centerY)
        {
            double radianDegrees = angle.GetRadianDegrees();
            int newX, newY;
            // newX=(x-a)cosθ-(y-b)sinθ+a
            newX = (int)Math.Round((x - centerX) * Math.Cos(radianDegrees) - (y - centerY) * Math.Sin(radianDegrees) + centerX, 0);
            // newY=(x-a)sinθ-(y-b)cosθ+b
            newY = (int)Math.Round((x - centerX) * Math.Sin(radianDegrees) - (y - centerY) * Math.Cos(radianDegrees) + centerY, 0);
            return new Point(newX, newY);
        }
        /// <summary>
        /// 消除的行数与当前摆放的板块中被消除的小方块的格数的乘积
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int ErodedPieceCellsMetric2(this BlockControl[,] grid, BlockShapeBase piece)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            bool status = false;
            int rowNumber = 0;
            int pieceCount = 0;
            fixed (BlockControl* set = grid, tempPiece = piece.BlockControls)
            {
                for (int i = rows - 1; i >= 0; i--)
                {
                    status = true;
                    for (int j = 0; j < cols; j++)
                    {
                        BlockControl* block = set + i * cols + j;
                        if (*block == null)
                        {
                            status = false;
                            break;
                        }
                    }
                    if (status)
                    {
                        ++rowNumber;
                        for (int j = 0; j < cols; j++)
                        {
                            BlockControl* block = set + i * cols + j;
                            for (int k = 0; k < piece.BlockControls.Length; k++)
                            {
                                if ((*block).Id == (*(tempPiece + k)).Id)
                                {
                                    ++pieceCount;
                                }
                            }
                        }
                    }
                }
            }

            return rowNumber * pieceCount;
        }
        public unsafe static int ErodedPieceCellsMetric(this BlockControl[,] grid, BlockShapeBase piece)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int rowNumber = 0;
            int pieceCount = 0;

            // 固定grid的首地址
            fixed (BlockControl* gridPtr = grid)
            {
                // 逐行从下到上检查是否已满
                for (int i = rows - 1; i >= 0; i--)
                {
                    bool isFull = true;
                    for (int j = 0; j < cols; j++)
                    {
                        // 如果找到空格，则该行不满
                        if (gridPtr[i * cols + j] == null)
                        {
                            isFull = false;
                            break;
                        }
                    }
                    if (isFull)
                    {
                        rowNumber++; // 增加消除的行数
                        pieceCount = 0; // 重置板块内被消除的小方块计数

                        // 检查该行中的每个小方块是否属于当前板块
                        for (int j = 0; j < cols; j++)
                        {
                            if (gridPtr[i * cols + j] != null && piece.BlockControls.Contains(gridPtr[i * cols + j]))
                            {
                                pieceCount++; // 增加计数
                            }
                        }
                    }
                }
            }

            // 返回消除的行数与被消除的小方块格数的乘积
            return rowNumber * pieceCount;
        }
        /// <summary>
        /// 获取行变换数
        /// 行变换数。按行遍历，从哪一行有方块开始计算，边界定义为没有方块，从方块到空记作一次变换，从空到有方块在记作一次变化
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardRowTransitions2(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int i, j, transitions = 0, curRow;
            fixed (BlockControl* blocks = grid)
            {
                for (i = 0; i < rows; i++)
                {
                    curRow = i * cols;
                    for (j = 0; j < cols-1; j++)
                    {
                        var first = blocks + curRow + j;
                        var second = first + 1;
                        if(*first == null && *second != null || *first != null && *second == null)
                            transitions++;
                    }
                }
            }

            return transitions;
        }
        public unsafe static int GetBoardRowTransitions(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int transitions = 0;
            bool hasBlocks = false;

            fixed (BlockControl* blocks = grid)
            {
                // 找到第一行有方块的行
                int firstRowWithBlocks = rows;
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        if (blocks[i * cols + j] != null)
                        {
                            firstRowWithBlocks = i;
                            hasBlocks = true;
                            break;
                        }
                    }
                    if (hasBlocks) break;
                }

                // 如果没有方块，返回0
                if (!hasBlocks) return 0;

                // 从找到的第一行开始计算变换数
                for (int i = firstRowWithBlocks; i < rows; i++)
                {
                    bool prevHasBlock = blocks[i * cols + 0] != null; // 前一个方块是否存在
                    for (int j = 1; j < cols; j++)
                    {
                        bool currentHasBlock = blocks[i * cols + j] != null;
                        if (prevHasBlock != currentHasBlock)
                        {
                            transitions++;
                        }
                        prevHasBlock = currentHasBlock;
                    }
                }
            }

            return transitions;
        }
        /// <summary>
        /// 获取列变换数
        /// 列变换数：同行变换数，只不过换成了按列遍历。
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardColTransitions2(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int i, j, transitions = 0;
            fixed (BlockControl* blocks = grid)
            {
                for (j = 0; j < cols; j++)
                {
                    var current = blocks + j;
                    for (i = 0; i < rows-1; i++)
                    {
                        var first = *current;
                        current += cols;
                        var second = *current;
                        if (first == null && second != null || first != null && second == null)
                            transitions++;
                    }
                }
            }
            return transitions;
        }
        public unsafe static int GetBoardColTransitions(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int transitions = 0;

            fixed (BlockControl* blocks = grid)
            {
                for (int j = 0; j < cols; j++) // 按列遍历
                {
                    bool prevHasBlock = blocks[j] != null; // 上一行的列是否有方块
                    for (int i = 1; i < rows; i++) // 从第二行开始遍历
                    {
                        bool currentHasBlock = blocks[i * cols + j] != null;
                        if (prevHasBlock != currentHasBlock) // 如果与上一行的状态不同，计数
                        {
                            transitions++;
                        }
                        prevHasBlock = currentHasBlock; // 更新状态
                    }
                }
            }

            return transitions;
        }
        /// <summary>
        /// 获取空洞数
        /// 解释：
        ///     空洞数，空洞指的是，每列中某个方块下面没有方块的空白位置，该空白可能由 1 个单位或多个单位组成，但只要没有被方块隔断，
        ///     都只算一个空洞。注意，空洞的计算以列为单位，若不同列的相邻空格连在一起，不可以将它们算作同一个空洞。
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardBuriedHoles2(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0) - 1;
            int cols = grid.GetLength(1);
            int i, j, holes = 0;
            bool IsSolid = false;
            fixed (BlockControl* blocks = grid)
            {
                for (j = 0; j < cols; j++)
                {
                    var current = blocks + j;
                    IsSolid = false;
                    for (i = 0; i < rows; i++)
                    {
                        if ((*current) != null)
                        {
                            IsSolid = true;
                        }
                        else
                        {
                            if(IsSolid)
                                ++holes;
                        }
                        current += cols;
                    }
                }
            }

            return holes;
        }
        public unsafe static int GetBoardBuriedHoles(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int holes = 0;

            fixed (BlockControl* blocks = grid)
            {
                for (int j = 0; j < cols; j++) // 按列遍历
                {
                    bool inHole = false; // 标记是否处于空洞中
                    for (int i = 0; i < rows; i++) // 从底部开始向上遍历
                    {
                        if (blocks[i * cols + j] == null) // 如果当前位置为空
                        {
                            if (!inHole) // 如果之前不是空洞，现在进入空洞
                            {
                                inHole = true; // 标记为空洞开始
                            }
                        }
                        else
                        {
                            if (inHole) // 如果当前位置有方块，且之前是空洞
                            {
                                holes++; // 空洞结束，增加空洞数
                                inHole = false; // 重置空洞标记
                            }
                        }
                    }
                    // 如果列的顶部是空洞的一部分，需要计数
                    if (inHole)
                    {
                        holes++;
                    }
                }
            }

            return holes;
        }
        /// <summary>
        /// 获取井数
        /// 解释：
        ///     井数，与字面意义一样–水井一样的个数。井指的是某一列中，两边都有方块的连续空格，（左右两侧看成一个环，不算做边界）。
        ///     还需要注意井深度，井的深度是连续累加的，例如：若一个井由 1 个方块组成，则为 1 ；若由连续 3 个组成，则和为 1 + 2 + 3 
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardWells2(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0) - 1;
            int cols = grid.GetLength(1);
            int i, j, wells = 0, currentWellDepth;
            fixed (BlockControl* blocks = grid)
            {
                int curRow;
                for (j = 0; j < cols; j++)
                {
                    currentWellDepth = 0;
                    for (i = rows; i >= 0; i--)
                    {
                        BlockControl* temp = blocks + i * cols;
                        // 检查当前单元格是否是一个洞并且被块包围
                        if ((*(temp + j)) == null &&
                            (*(temp + (j - 1 + cols) % cols)) != null &&
                            (*(temp + (j + 1) % cols)) != null)
                        {
                            // 增加当前井深并将其添加到井深总和中
                            currentWellDepth++;
                            wells += currentWellDepth;
                        }
                        else
                            currentWellDepth = 0;
                    }
                }
            }

            return wells;
        }
        public unsafe static int GetBoardWells(this BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int wells = 0;

            fixed (BlockControl* blocks = grid)
            {
                for (int j = 0; j < cols; j++)
                {
                    int wellDepth = 0;
                    bool inWell = false;

                    for (int i = 0; i < rows; i++)
                    {
                        BlockControl* current = blocks + i * cols + j;
                        BlockControl* left = current - 1;
                        BlockControl* right = current + 1;

                        // 检查是否在列的边界，如果是，则使用模运算确保指针在数组内
                        if (j == 0) left = current + cols - 1;
                        if (j == cols - 1) right = current - 1;

                        // 检查当前单元格是否为空，并且左右两边是否有方块
                        if (*current == null && *left != null && *right != null)
                        {
                            if (!inWell) // 如果当前不在井中，则开始计算井深度
                            {
                                inWell = true;
                            }
                            wellDepth++; // 增加井的深度
                        }
                        else
                        {
                            if (inWell) // 如果当前在井中，计算井的总深度
                            {
                                wells += wellDepth * (wellDepth + 1) / 2;
                                inWell = false; // 重置井状态
                                wellDepth = 0;
                            }
                        }
                    }

                    // 如果列的顶部是井的一部分，需要计算井的深度
                    if (inWell)
                    {
                        wells += wellDepth * (wellDepth + 1) / 2;
                    }
                }
            }

            return wells;
        }
        /// <summary>
        /// 落差高度
        /// </summary>
        /// <param name="piece"></param>
        /// <param name="grid"></param>
        /// <returns></returns>
        public static int DropHeight(this BlockControl[,] grid, BlockShapeBase piece)
        {
            int dy = 0;
            while (piece.Move(grid, DirectionType.Down))
            {
                dy++;
            }
            
            return dy;
        }
        /// <summary>
        /// 深拷贝
        /// </summary>
        /// <param name="originalArray"></param>
        /// <returns></returns>
        public static BlockControl[,] DeepCloneBlockControlArray(this BlockControl[,] originalArray)
        {
            BlockControl[,] newArray = new BlockControl[originalArray.GetLength(0), originalArray.GetLength(1)];

            for (int i = 0; i < originalArray.GetLength(0); i++)
            {
                for (int j = 0; j < originalArray.GetLength(1); j++)
                {
                    BlockControl originalBlockControl = originalArray[i, j];
                    if (originalBlockControl != null)
                    {
                        newArray[i, j] = originalBlockControl.Clone();
                    }
                }
            }

            return newArray;
        }
    }
}
